﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Xant.Querier.Interface
{
    /// <summary>
    /// 关系运算符
    /// </summary>
    public enum RelationalOperator
    {

        /// <summary>
        /// 等于
        /// </summary>
        EqualTo,

        /// <summary>
        /// 大于
        /// </summary>
        GreaterThan,

        /// <summary>
        /// 大于等于
        /// </summary>
        GreaterThanOrEqualTo,

        /// <summary>
        /// 小于
        /// </summary>
        LessThan,

        /// <summary>
        /// 小于等于
        /// </summary>
        LessThanOrEqualTo,

        /// <summary>
        /// 不等于
        /// </summary>
        NotEquals,

        /// <summary>
        /// 包含
        /// </summary>
        Contains,

        /// <summary>
        /// 头部匹配(以指定字符串开始)
        /// </summary>
        StartsWith,

        /// <summary>
        /// 尾部匹配(以指定字符串结束)
        /// </summary>
        EndsWith,

        /// <summary>
        /// 包含于
        /// </summary>
        In,

        /// <summary>
        /// 不包含于
        /// </summary>
        NotIn,

    }

    /// <summary>
    /// 一元逻辑运算符(NOT)
    /// </summary>
    public enum UnaryLogicalOperator
    {

        /// <summary>
        /// 取非
        /// </summary>
        Not,
    }

    /// <summary>
    /// 逻辑运算符(ANT/OR)
    /// </summary>
    public enum LogicalOperator
    {

        /// <summary>
        /// 并且
        /// </summary>
        And,

        /// <summary>
        /// 或者
        /// </summary>
        Or,
    }

    /// <summary>
    /// 数学运算符(加/减/乘/除/求和/计数/平方)
    /// </summary>
    public enum MathOperator
    {

        /// <summary>
        /// 加
        /// </summary>
        Plus,

        /// <summary>
        /// 减
        /// </summary>
        Minus,

        /// <summary>
        /// 加
        /// </summary>
        Multiply,

        /// <summary>
        /// 除
        /// </summary>
        Divide,

        /// <summary>
        /// 求和
        /// </summary>
        Sum,

        /// <summary>
        /// 计数
        /// </summary>
        Count,

        /// <summary>
        /// 平方
        /// </summary>
        Power,
    }

    /// <summary>
    /// 运算符优先级辅助类，数字越大越优先
    /// </summary>
    public static class OperatorPrecedence
    {
        private static readonly Dictionary<MathOperator, int> precedenceOfMathOptr;
        private static readonly Dictionary<LogicalOperator, int> precedenceOfLogicOptr;

        static OperatorPrecedence()
        {
            precedenceOfMathOptr = new Dictionary<MathOperator, int>();
            precedenceOfLogicOptr = new Dictionary<LogicalOperator, int>();
            /*算术运算符*/
            //加、减运算优先级最低
            precedenceOfMathOptr.Add(MathOperator.Plus, 1);
            precedenceOfMathOptr.Add(MathOperator.Minus, 1);
            //乘、除运算优先级较高
            precedenceOfMathOptr.Add(MathOperator.Multiply, 2);
            precedenceOfMathOptr.Add(MathOperator.Divide, 2);
            //其他算术运算符会转换为函数调用，所以无视优先级
            precedenceOfMathOptr.Add(MathOperator.Sum, -1);
            precedenceOfMathOptr.Add(MathOperator.Count, -1);
            precedenceOfMathOptr.Add(MathOperator.Power, -1);
            /*逻辑运算符*/
            precedenceOfLogicOptr.Add(LogicalOperator.Or, 1);
            precedenceOfLogicOptr.Add(LogicalOperator.And, 2);
        }

        /// <summary>
        /// 获得代表指定运算符的优先级的数字，数字越大越优先
        /// </summary>
        public static int GetPrecedence(this MathOperator optr)
        {
            return precedenceOfMathOptr[optr];
        }

        /// <summary>
        /// 获得代表指定运算符的优先级的数字，数字越大越优先
        /// </summary>
        /// <param name="optr"></param>
        /// <returns></returns>
        public static int GetPrecedence(this LogicalOperator optr)
        {
            return precedenceOfLogicOptr[optr];
        }

        /// <summary>
        /// 用于比较的运算符<see cref="optr"/>优先级是否低于参照的运算符<see cref="compare2"/>
        /// </summary>
        /// <param name="optr">用于比较的运算符</param>
        /// <param name="compare2">参照的运算符</param>
        /// <returns></returns>
        public static bool IsLowerPriorityThan(this MathOperator optr, MathOperator compare2)
        {
            var precedence1 = optr.GetPrecedence();
            var precedence2 = compare2.GetPrecedence();
            if (precedence1 < 0 || precedence2 < 0)//两者有任意一个忽略优先级
                return false;
            return precedence1 < precedence2;
        }

        /// <summary>
        /// 用于比较的运算符<see cref="optr"/>优先级是否低于参照的运算符<see cref="compare2"/>
        /// </summary>
        /// <param name="optr">用于比较的运算符</param>
        /// <param name="compare2">参照的运算符</param>
        /// <returns></returns>
        public static bool IsLowerPriorityThan(this LogicalOperator optr, LogicalOperator compare2)
        {
            var precedence1 = optr.GetPrecedence();
            var precedence2 = compare2.GetPrecedence();
            return precedence1 < precedence2;
        }
    }

}
